using System;
using System.Collections.Generic;
using System.Data;
using System.Text;

namespace SchemaProvider
{
    public abstract class ProcedureCodeProviderBase : IProcedureCodeProvider
    {

        public string ToFieldName(string parameterName)
        {
            return "_" + CodeUtility.PascalCaseToCamelCase(ToPropertyName(parameterName));
        }


        public abstract string ToPropertyName(string parameterName);

        protected abstract string DBTypeToCSType(string dbType);

      
        #region IProcedureCodeProvider Members

        public virtual string MapMemberVariablesBlock(string procedureName, List<ProcedureParameter> parameters)
        {
            List<ProcedureParameter> parametersOfProcedure = GetParametersOfProcedure(procedureName, parameters);
            StringBuilder content = new StringBuilder();
            if (parametersOfProcedure.Count <= 0)
            {
                return content.ToString();
            }
            content.Append("\n");
            foreach (ProcedureParameter parameter in parametersOfProcedure)
            {
                string parameterName = parameter.ParameterName;

                if (string.IsNullOrEmpty(parameter.ParameterName))
                {
                    parameterName = CodeUtility.EmptyDataEntity;
                }

                content.Append(CodeUtility.CreateTabSpaces(2) + "private " + DBTypeToCSType(parameter.ParameterType) + " " +
                    this.ToFieldName(parameterName) + ";\n");
            }
            return content.ToString();
            
        }

        public virtual string MapPropertiesBlock(string procedureName, List<ProcedureParameter> parameters)
        {
            List<ProcedureParameter> parametersOfProcedure = GetParametersOfProcedure(procedureName, parameters);
            StringBuilder content = new StringBuilder();
            if (parametersOfProcedure.Count <= 0)
            {
                return content.ToString();
            }

            content.Append("\n");
            foreach (ProcedureParameter parameter in parametersOfProcedure)
            {
                string parameterName = parameter.ParameterName;

                if (string.IsNullOrEmpty(parameter.ParameterName))
                {
                    parameterName = CodeUtility.EmptyDataEntity;
                }

                string direction = (parameter.IsOutput == "1") ? "Direction=ParameterDirection.Output" : "Direction=ParameterDirection.Input";
                content.Append(CodeUtility.CreateTabSpaces(2));
                content.Append("[Parameter(Name = \"" + parameterName + "\"," + direction + ")]\n");
                string propertyName = this.ToPropertyName(parameterName);
                string fieldName = this.ToFieldName(parameterName);

                content.Append(CodeUtility.CreateTabSpaces(2) + "public " + DBTypeToCSType(parameter.ParameterType) + " " + propertyName + "\n");
                content.Append(CodeUtility.CreateTabSpaces(2) + "{\n");
                content.Append(CodeUtility.CreateTabSpaces(3) + "get\n");
                content.Append(CodeUtility.CreateTabSpaces(3) + "{\n");
                content.Append(CodeUtility.CreateTabSpaces(4) + "return " + fieldName + ";\n");
                content.Append(CodeUtility.CreateTabSpaces(3) + "}\n");
                content.Append(CodeUtility.CreateTabSpaces(3) + "set\n");
                content.Append(CodeUtility.CreateTabSpaces(3) + "{\n");
                content.Append(CodeUtility.CreateTabSpaces(4) + fieldName + "=value;\n");
                content.Append(CodeUtility.CreateTabSpaces(3) + "}\n");
                content.Append(CodeUtility.CreateTabSpaces(2) + "}\n\r");
            }
            return content.ToString();
        }

        private List<ProcedureParameter> GetParametersOfProcedure(string procedureName, List<ProcedureParameter> parameters)
        {
            List<ProcedureParameter> parametersOfProcedure=parameters.FindAll(
                delegate(ProcedureParameter parameter){return parameter.ProcedureName==procedureName;});
            return parametersOfProcedure;
        }

        #endregion

        #region ICodeProvider Members

        public virtual string MapClassAttribute(string name)
        {
            return "[Procedure(Name = \"" + name + "\")]";
        }

        public abstract string MapClassName(string name);

        public virtual string MapBaseClassName(string name)
        {
            string baseClassName = "StoredProcedure";
            return baseClassName + "<" + this.MapClassName(name) + ">";
        }

        #endregion
    }
}
